package org.gaaidou.ptarmigan.springboot.core.common;

import org.gaaidou.ptarmigan.springboot.core.exception.QueueOverloadException;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Supplier;

public final class QueueHelper<T> {

    private final ArrayBlockingQueue<T> queue;
    private int waitMillisecond = 100;

    public QueueHelper(int size, int waitMillisecond, Supplier<T> initFn) {
        this.waitMillisecond = waitMillisecond;
        queue = new ArrayBlockingQueue<>(size);
        for (int index = 0; index < size; index++) {
            queue.offer(initFn.get());
        }
    }

    public <K> K call(Function<T, K> fn) {
        T data = null;
        try {
            data = queue.poll(waitMillisecond, TimeUnit.MILLISECONDS);
            if (null == data) {
                throw new QueueOverloadException();
            }
            return fn.apply(data);
        } catch (InterruptedException e) {
            throw new QueueOverloadException("interrupted exception");
        } finally {
            releaseIfNotNull(data);
        }
    }

    private void releaseIfNotNull(T data) {
        if (null != data) {
            queue.offer(data);
        }
    }
}
